<?php
/**
* Parse a given QIF file and load the transactions in the DB.
* QIF format is line based with each line being one of the following:
* 
* ^ end of items, D date, T amount, C cleared, P payee, M memo, A address, L category, S cartegory split, E memo split, $ amount split
*
* As this is a very poor format, we are loosy as well and we load what we can parse, everything is ignored
* Date management is a nightmare so we will load as we can and offer the possibility to edit the dates
*  
*  @author       Fabrice Douteaud <admin@clearbudget.net>
* @package      actions
* @access       public
*/

/***********************************************************************

  Copyright (C) 2008  Fabrice Douteaud (admin@clearbudget.net)

    This file is part of ClearBudget.

    ClearBudget is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    ClearBudget is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with ClearBudget.  If not, see <http://www.gnu.org/licenses/>.


************************************************************************/
//prevent direct access
if(!defined('ENGINEON')) die('Direct access forbidden');
global $context;
$db = class_db::getInstance();

// a flag that tells us we have an invalid date format
$invalidDateFormat = false;

// First we check if we have the correct data from the client
// check if we get there from a POST with a file uploaded
if($_SERVER["REQUEST_METHOD"] != 'POST' || !isset($_FILES["datafile"])) {
  $return['error'] = true;
  $return['msg'] = $keys->error_ImproperCall;
  class_debug::addMsg(__FILE__, 'called to upload file not in POST and no file is present', DEBUGINFO);
  return;
  }

// check if the file has been uploaded correctly
if(!file_exists($_FILES["datafile"]['tmp_name'])) {
  $return['error'] = true;
  $return['msg'] = $keys->error_ImproperQifFile;
  return;
  }

// a bit debuging as to check the locale parameters (important for date parsing)
class_debug::addMsg(__FILE__, 'Parsing QIF dates as '.$context->QIFLocaleType, DEBUGDEBUG);
$dateFormat = $context->QIFLocaleType;

// be sure we detect the right line ending
@ini_set('auto_detect_line_endings', true);
  
// load the file in an array
$lines = @file($_FILES["datafile"]['tmp_name']);
// if loading was unsuccessful, we exit with error (file type not correct most probably)
if($lines == false) {
  $return['error'] = true;
  $return['msg'] = $keys->error_ImproperQifFile2;
  return;
  }

/*
We removed the following checks as many QIF files do not present themselves with these :-(
Should start with !Type and the type should be Bank but, hey, it is not that way in real life!
*/
// check if the first line starts with '!Type:' which should be the case in a valid QIF file
//if(strtoupper(substr($lines[0], 0, 6)) != '!TYPE:') {
//  $return['error'] = true;
//  $return['msg'] = $keys->error_ImproperQifFile3;
//  return;
//  }

// get the type, must be Bank
//$type = trim(substr($lines[0], 6, strlen($lines[0])));
// as this is sometimes translated, this is completely useless so we do not check for the Type :-(

// array to hold each item from the file
$item = array();
// counter of lines processed
$lineCounter = 1;
// counter of item inserted successfuly
$insertCounter = 0;  
// counter of item not inserted because duplicated
$duplicateCounter = 0;  
// array to hold and compare magic number (but still allows n equal fields per file)
$magics = array();
// get today's date
$today = date("Y-m-d");

// insert a record in the batch records
$db->addFields('originalFileName', $_FILES['datafile']['name']);
$db->addFields('importCount', 0);
$db->addFields('importDuplicate', 0);
$db->addFields('importDate', $today);
$db->addFields('importType', IMPORTQIFFILE);
$importId = $db->insert('t_imports');

// go line by line to process the file
foreach($lines as $line) {
  $lineCounter++;
  if($line != '') {
    // get the line identifier
    $id = substr($line, 0, 1);
    // get the content of that line
    $content = trim(substr($line, 1, strlen($line)));
    switch ($id) {
      case '^':
        set_time_limit(10); 
        // add the null category
        $item['category'] = '1';
        // add the import batch ID
        $item['importId'] = $importId;
        // add the current date
        $item['createDate'] = $today;
        // create the magic string
        $magic = $item['operationDate'].$item['amount'].$item['payee'];
        //echo '$magic: '.$magic.'<br/>';
        $magics[$magic][] = $lineCounter;
        $magicCounter = count($magics[$magic]);
        //echo '$magicCounter: '.$magicCounter.'<br/>';
        if($magicCounter > 1) {
          // add the checksum from the magic + the magic counter
          $item['checksum'] = md5($magic).'-'.$magicCounter;
          }
        else {
          // add the checksum from the magic
          $item['checksum'] = md5($magic);
          }
        
        // insert the row
        foreach($item as $field=>$value) {
          $db->addFields($field, $value);
          }
        
        if($db->insert('t_items') !== false) {
          //echo 'inserted<br/>';
          $insertCounter++;
          }
        else {
          $duplicateCounter++;
          $magics[$magic] = null;
          }
        $item = null;
      break;
      case 'D':
        $item['operationDate'] = formatQIFDate($content, $invalidDateFormat);
      break;
      case 'T':
        $item['debit'] = '0';
        if($content == '') continue;
        $st = substr($content, 0, 1);
        if($st == '-') {
          $item['debit'] = '1';
          $content = substr($content, 1, strlen($content)-1);
          }
        $item['amount'] = cleanAmount($content);
      break;
      case 'C':
        $item['cleared'] = $content;
      break;
      case 'P':
        $item['payee'] = clean($content);
      break;
      case 'M':
        $item['memo'] = clean($content);
      break;
      default:
      break;
      } // switch
    } // if
  } // foreach

if(!$invalidDateFormat && ($insertCounter > 0 || $duplicateCounter > 0)) {
  // update the import record with the data
  $db->addFields('importCount', $insertCounter);
  $db->addFields('importDuplicate', $duplicateCounter);
  $db->addWhere('id', '=', $importId);
  $db->update('t_imports');

  $return['msg'] = sprintf($_FILES['datafile']['name'].' - '.$keys->text_importedTransactions.': %d, '.$keys->text_duplicatedRecords.': %d', $insertCounter, $duplicateCounter);
  $return['error'] = false;
  $return['importCount'] = $insertCounter;
  $return['importId'] = $importId;
  }
else {
  // remove everything as this is not a valid import (dates are malformed)
  $db->addWhere('id', '=', $importId);
  $db->delete('t_imports');
  $db->addWhere('importId', '=', $importId);
  $db->delete('t_items');

  $return['error'] = true;
  $return['msg'] = $keys->error_ImproperQifFile4;
  }
?>